﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RabbitMQ.Client;
using System.Threading;
using RabbitMQ.Client.Events;
using System.IO;
using System.Diagnostics;

namespace JWUX.Supermarket.MQL
{
    public abstract class Client : IDisposable
    {
        #region 成员

        /// <summary>
        /// RabbitMQ ConnectionFactory
        /// </summary>
        protected IConnection _connection;

        protected IModel _channel;

        private System.Timers.Timer _reTryTimer;

        /// <summary>
        /// RabbitMQ 服务器名称
        /// </summary>
        private string _hostName;

        /// <summary>
        /// 尝试连接的次数
        /// </summary>
        private int _triedCount = 0;

        private Thread _thread;

        protected const string QUEUE_REQUEST = "JWUX.Supermarket.Requests";
        protected const string QUQUE_REPLY = "JWUX.Supermarket.Replies";
        protected bool _noAck = true;

        #endregion

        #region 事件

        /// <summary>
        /// 表示处理与消息服务器建立连接的方法
        /// </summary>
        /// <param name="hostName">服务器名称</param>
        /// <param name="triedCount">已经尝试连接的次数</param>
        public delegate void IConnectionCreateEventHandler(string hostName, int triedCount);
        public event IConnectionCreateEventHandler ConnectionCreating;
        public event IConnectionCreateEventHandler ConnectionCreated;
        public event IConnectionCreateEventHandler ConnectionCreateFailed;

        /// <summary>
        /// 表示与消息服务器断开连接的处理方法
        /// </summary>
        /// <param name="reason"></param>
        public delegate void IConnectionDisconnectedEventHandler(ShutdownEventArgs reason);
        public event IConnectionDisconnectedEventHandler ConnectionDisconnected;

        /// <summary>
        /// 表示从消息服务器接收消息的方法
        /// </summary>
        /// <param name="message"></param>
        public delegate void MessageReceiveEventHandler(string message);
        public event MessageReceiveEventHandler MessageReceived;

        /// <summary>
        /// 接收到消息的事件
        /// </summary>
        /// <param name="message"></param>
        public void OnMessageReceived(string message)
        {
            if (MessageReceived != null)
            {
                MessageReceived(message);
            }
        }

        public void OnCreating()
        {
            if (ConnectionCreating != null)
            {
                ConnectionCreating(_hostName, ++_triedCount);
            }
        }

        public void OnCreated()
        {
            if (ConnectionCreated != null)
            {
                ConnectionCreated(_hostName, _triedCount);
            }
            _triedCount = 0;
        }

        public void OnCreateFailed()
        {
            if (ConnectionCreateFailed != null)
            {
                ConnectionCreateFailed(_hostName, _triedCount);
            }
        }

        public void OnDisconnected(ShutdownEventArgs reason)
        {
            if (ConnectionDisconnected != null)
            {
                ConnectionDisconnected(reason);
            }
        }

        #endregion

        #region 属性

        public string Exchange
        {
            get;
            private set;
        }

        #endregion

        #region 构造和方法

        public Client(string hostName, string pcName)
        {
            _hostName = hostName;
            Exchange = pcName;

            _thread = new Thread(SubscriptionMessage);
            _thread.IsBackground = true;
            _thread.Start();
            //_reTryTimer = new System.Timers.Timer(5000);
            //_reTryTimer.Elapsed += new System.Timers.ElapsedEventHandler(TryToConnection);
        }

        void ConnectionShutdown(IConnection connection, ShutdownEventArgs reason)
        {
            OnDisconnected(reason);
            //_reTryTimer.Start();
        }

        void TryToConnection()
        {
            try
            {
                OnCreating();

                _connection = BSConnection.GetConnection(_hostName);
                _connection.ConnectionShutdown +=
                    new RabbitMQ.Client.Events.ConnectionShutdownEventHandler(ConnectionShutdown);
                //_reTryTimer.Stop();

                OnCreated();
            }
            catch
            {
                OnCreateFailed();
            }
        }

        void IDisposable.Dispose()
        {
            _reTryTimer.Close();
            _reTryTimer = null;

            if (_connection != null && _connection.IsOpen)
            {
                _connection.Close();
                _connection = null;
            }
        }

        public abstract bool SendMessage(string message);

        public abstract void GetSingleMessage();

        /// <summary>
        /// 订阅模式获取消息
        /// </summary>
        private void SubscriptionMessage()
        {
            string msg = string.Empty;
            try
            {
                QueueingBasicConsumer consumer = new QueueingBasicConsumer(_channel);
                _channel.BasicConsume(QUEUE_REQUEST, false, consumer);
                //消息将会异步传递
                while (true)
                {
                    try
                    {
                        BasicDeliverEventArgs e = consumer.Queue.Dequeue() as BasicDeliverEventArgs;
                        //Handle the delivery
                        msg = Encoding.Default.GetString(e.Body);
                        //将消息从队列中删除
                        _channel.BasicAck(e.DeliveryTag, false);

                        OnMessageReceived(msg);
                    }
                    catch { }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }

        #endregion
    }
}
